//
//  randomtestcard.c
//  Dominion
//
//  Eric Hook
//  hooke@onid.orst.edu
//  CS362 Winter 2014
//

#include "dominion.h"
#include "dominion_helpers.h"
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include "rngs.h"
#include "math.h"
#include <time.h>
#include <stdlib.h>

/////////////// randtestcard.c tests functionality of cutpurse ///////////////

void setUpRandomizerCutPurse();
void testCutpurseCard (int playerTurn, struct gameState *G);
int getCopperCount  (struct gameState *G, int player);
int compareCopperCounts (struct gameState *Gpost, struct gameState *Gpre);
int compareCoins (struct gameState *Gpost, struct gameState *Gpre);
int makeRandomHand (int player, int numCards)  ;

////////////////////////////////////////////////////////////////////////////

int seed = 1;
static int TEXT_FEEDBACK = 0;
int defaultKingdomCards[10] = {adventurer, council_room, feast, gardens, mine, remodel, smithy, village, baron, great_hall}; //Default cards, as defined in playDom
int treasureCards[4] = {copper, silver, gold};
struct gameState *G;
struct gameState *Gpost;
struct gameState *Gpre;

#define NUM_TESTS 1000
#define NUM_UNIQUE_CARDS 30

struct gameState gameStateRandomizer () {
    int i, numPlayers ;
    G     = malloc(sizeof(struct gameState));
    Gpost = malloc(sizeof(struct gameState));
    Gpre  = malloc(sizeof(struct gameState));
    //srand((int)time(NULL));                           // doesn't update quickly enough - need fix
    srand(seed);
    memset(G, 0, sizeof(struct gameState));             // clear the game state
    initializeGame(2, defaultKingdomCards, seed, G);
    
    // Set up random gamestate//////////////
    G->numPlayers = rand() % 3 + 2;                     //random reasonable (allowed) num players 2-4
    numPlayers = G->numPlayers;
    for (i = 0; i < numPlayers; i++){
        G->deckCount[i]     = rand() % MAX_DECK;         //random reasonable num deckCount
        G->discardCount[i]  = rand() % MAX_DECK;         //random reasonable num discardCount
        if (rand()% 10 < 5){
            G->handCount[i] = rand() % MAX_HAND;         //random up to very large num handCount
        }
        else {
            G->handCount[i] = rand() % 5 + 5;           // a more reasonable hand size
        }
        //G->handCount[i] = 5;  //                      //for testing with standard size handCount
        
    }
    G->playedCardCount = rand() % MAX_DECK;
    G->whoseTurn = rand() % numPlayers;
    G->coins = 1;
    for (int i = 0; i < G->numPlayers; i++){
        makeRandomHand(i, G->handCount[i-1]);                           // make random card hand for each player
    }
    memcpy (Gpost, G, sizeof(struct gameState));
    memcpy (Gpre,  G, sizeof(struct gameState));
    return *G;
}


void setUpRandomizerCutPurse(){
    for (int i = 0; i < NUM_TESTS; i++) {
        seed +=3;
        gameStateRandomizer();                          // make a brand new game state
        testCutpurseCard(Gpost->whoseTurn, Gpre);
        
    }
    //printf ("ALL TESTS OK - well not really. The asserts were commented out temporarily.\n");
}


void testCutpurseCard (int playerTurn, struct gameState *gs) {
    printf("***BEFORE cutpurse()***\n");
    for (int i = 0; i < gs->numPlayers; i++) {
        int postCopper = getCopperCount(Gpost, i);
        int preCopper  = getCopperCount(Gpre, i);
        int preCoins;
        updateCoins(Gpre->whoseTurn, gs, 0);
        preCoins = Gpre->coins;
        if (whoseTurn(Gpre) == i) {
            printf("    TURN player %i > pre-copper: %i, post-copper %i, coins %i ***turn player should lose 0 copper in hand!\n", i, preCopper, postCopper, preCoins);
            //assert ( postCopper == preCopper);           // current player should not lose copper
        }
        if (whoseTurn(Gpost) != i) {
            if (postCopper >= 2){
                printf("NON-TURN player %i > pre-copper: %i, post-copper %i ***non-turn player SHOULD lose up to 2  copper in hand!\n", i, preCopper, postCopper);
                //assert (postCopper == preCopper+2);                           // player should have 2 less copper after card played
            }
            if (postCopper < 2){
                printf("NON-TURN player %i > pre-copper: %i, post-copper %i ***non-turn player SHOULD lose up to 2  copper in hand!\n", i, preCopper, postCopper);
                //assert ( preCopper == 0 );                                    // player should have ZERO copper after card played
            }
        }
    }
    printf("***call cutpurse()***\n");
    printf("***AFTER cutpurse()***\n");
    cardEffect(cutpurse, 0, 0, 0, Gpost, 2, 0);             // call card effect for cutpurse with new random game state
    
    for (int i = 0; i < Gpre->numPlayers; i++) {
        int preCopper  = getCopperCount(Gpre, i);
        int postCopper = getCopperCount(Gpost, i);
        int postCoins  = Gpost->coins;
        if (whoseTurn(Gpre) == i) {
            printf("    TURN player %i > pre-copper: %i, post-copper %i, coins %i *** turn player should lose 0 copper in hand & gain 2 coins!\n", i, preCopper, postCopper, postCoins);
            //assert ( postCopper == preCopper);           // current player should not lose copper
        }
        if (whoseTurn(Gpost) != i) {
            if (postCopper >= 2){
                printf("NON-TURN player %i > pre-copper: %i, post-copper %i ***non-turn player SHOULD lose up to 2  copper in hand!\n", i, preCopper, postCopper);
                //assert (postCopper == preCopper+2);                           // player should have 2 less copper after card played
            }
            if (postCopper < 2){
                printf("NON-TURN player %i > pre-copper: %i, post-copper %i ***non-turn player SHOULD lose up to 2  copper in hand!\n", i, preCopper, postCopper);
                //assert ( preCopper == 0 );                                    // player should have ZERO copper after card played
            }
        }
        
    }

    compareCopperCounts (Gpre, Gpost);                  // ERROR in code**** non-turn player should lose 2 and not 1 copper if sufficient copper in hand!
    compareCoins(Gpre, Gpost);                          // post cutpurse shouild be +2 coins for player.
    
    printf ("!!!FINISHED CUTPURSE CARD EFFECT: int cardEffect(int card, int choice1, int choice2, int choice3, struct gameState *state, int handPos, int *bonus) : randomtestcard.c.\n");
}


int getCopperCount (struct gameState *gs, int player){
    int copperCount = 0;
            for (int j = 0; j < gs->handCount[player]; j++) {
                if (gs->hand[player][j] == copper) {
                    copperCount++;
                }
            }
            if (TEXT_FEEDBACK) printf("Player %i copper count is: %i.\n", player, copperCount);
    return copperCount;
}


int compareCopperCounts (struct gameState *Gpre, struct gameState *Gpost) {     //  make sure the copper count before and after card played is correct
    for (int i = 0; i < Gpost->numPlayers; i++) {
        int preCopper = getCopperCount(Gpre, i);
        int postCopper = getCopperCount(Gpost, i);
        if (whoseTurn(Gpost) == i) {
            if (TEXT_FEEDBACK) printf("    TURN player %i > pre-copper: %i, post-copper %i *** turn player should lose 0 copper in hand!\n", i, preCopper, postCopper);
            //assert ( postCopper == preCopper);           // current player should not lose copper
        }
        if (whoseTurn(Gpost) != i) {
            if (postCopper >= 2){                                               // subtract 2 copper IF non-turn player has 2 or more copper in hand
                if (TEXT_FEEDBACK) printf("NON-TURN player %i > pre-copper: %i, post-copper %i *** non-turn player should lose 2 not 1 copper if 2+ copper in hand!\n", i, preCopper, postCopper);
                //assert (postCopper == preCopper+2);                           // player should have 2 less copper after card played
            }
            if (postCopper < 2){
                if (TEXT_FEEDBACK) printf("NON-TURN player %i > pre-copper: %i, post-copper %i  *** non-turn player should lose 2 not 1 copper if 2+ copper in hand!\n", i, preCopper, postCopper);
                //assert ( preCopper == 0 );                                    // player should have ZERO copper after card played
            }
        }
    }
    return 0;
}


int makeRandomHand (int player, int numCards) {
    for (int i = 0; i < numCards; i++){
        if (rand()%10 < 9) {
            G->hand[player][i]=rand()% 3 + 4;                                   // balance the hand with some Treasure cards
        }
        else G->hand[player][i]=rand()% NUM_UNIQUE_CARDS;
    }
    return 0;
}


int compareCoins (struct gameState *Gpre, struct gameState *Gost){
    // assert (Gpost->coins = Gpre->coins + 2);   // two coins should be award for cutpurse card
    //printf("\nCompare coins: post cutpurse shouild be +2 coins for player. Pre: %i, Post: %i  *** PASS\n", Gpre->coins, Gpost->coins);
    return 0;   // 0 if true
}


int getRandomKingdomCard (int kindomCardSet[]){
    int numCardsInSet = ((sizeof(*kindomCardSet) / (sizeof(int))));
    return rand()%numCardsInSet;
}


int getRandomTreasureCard (){
    int treasureCards[] = {copper, silver, gold};
    return treasureCards[rand()%3];
}


int main () {
    setUpRandomizerCutPurse();
    return 0;
}